const { resolve } = require('path');
const { PROJECT_PATH } = require('../constant');
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const CompressionPlugin = require('compression-webpack-plugin');

module.exports = merge(common, {
    mode: 'production',
    devtool: false,
    target: 'browserslist',
    cache: false,
    output: {
        filename: `js/[name].[contenthash:8].js`,
        path: resolve(PROJECT_PATH, './dist'),
        assetModuleFilename: 'images/[name].[contenthash:8].[ext]',
    },
    plugins: [
        new CleanWebpackPlugin(),
        new MiniCssExtractPlugin({
            filename: 'css/[name].[contenthash:8].css',
            chunkFilename: 'css/[name].[contenthash:8].chunk.css',
            ignoreOrder: false,
        }),
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify('production'),
        }),
        new BundleAnalyzerPlugin({
            analyzerMode: 'server', // 开一个本地服务查看报告
            analyzerHost: '127.0.0.1', // host 设置
            analyzerPort: 8888, // 端口号设置
        }),
    ],
    optimization: {
        minimize: true,
        minimizer: [
            new CompressionPlugin({
                test: /\.(js|css|html|svg)$/,
                algorithm: 'gzip',
                exclude: /\/node_modules/,
                filename: '[path][base].gz',
            }),
            // css 压缩
            new CssMinimizerPlugin({
                minimizerOptions: {
                    preset: [
                        'default',
                        {
                            discardComments: { removeAll: true },
                        },
                    ],
                },
            }),
            // js 压缩
            new TerserPlugin({
                parallel: 8, //使用多进程并行运行来提高构建速度
                // test: /\.js(\?.*)?$/i,
                // include: /\/src/,
                exclude: /\/node_modules/,
                extractComments: 'all',
                extractComments: false,
                terserOptions: {
                    warnings: false,
                    parse: {},
                    compress: {
                        unused: true,
                        drop_debugger: true,
                        drop_console: true,
                        pure_funcs: ['console.log'], // 移除console
                    },
                    output: {
                        comments: false, // 去掉注释
                        beautify: false, // 使输出的代码尽可能紧凑
                    },
                },
            }),
        ],
        splitChunks: {
            // async表示只从异步加载得模块（动态加载import()）里面进行拆分
            // initial表示只从入口模块进行拆分
            // all表示以上两者都包括
            chunks: 'all',
            minSize: 30000, // 大于30k会被webpack进行拆包
            enforceSizeThreshold: 50000, //强制执行拆分且忽略其他限制
            minChunks: 1, // 被引用次数大于等于这个次数进行拆分
            // webpack 5 中引入了选项，通过确保拆分后保留的块的最小大小高于限制来避免零大小的模块
            minRemainingSize: 0,
            // import()文件本身算一个
            // 只计算js，不算css
            maxAsyncRequests: 30, // 最大的按需加载（异步）请求次数
            // 最大的初始化加载请求次数,为了对请求数做限制，不至于拆分出来过多模块
            // 入口文件算一个
            // 如果这个模块有异步加载的不算
            // 只算js，不算css
            // 通过runtimeChunk拆分出来的runtime不算在内
            // 如果同时又两个模块满足cacheGroup的规则要进行拆分，但是maxInitialRequests的值只能允许再拆分一个模块，那尺寸更大的模块会被拆分出来
            maxInitialRequests: 10,
            automaticNameDelimiter: '.', // 打包分隔符
            name: false,
            cacheGroups: {
                react: {
                    chunks: 'all',
                    name: 'react',
                    test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
                    priority: 20,
                    reuseExistingChunk: true,
                },
                antd: {
                    chunks: 'all',
                    name: 'antd',
                    test: /[\\/]node_modules[\\/](antd)[\\/]/,
                    priority: 20,
                    reuseExistingChunk: true,
                },
                icons: {
                    chunks: 'all',
                    name: 'icons',
                    test: /[\\/]node_modules[\\/](@ant-design)[\\/]/,
                    priority: 20,
                    reuseExistingChunk: true,
                },
                echarts: {
                    chunks: 'all',
                    name: 'echarts',
                    test: /[\\/]node_modules[\\/](echarts)[\\/]/,
                    priority: 20,
                    reuseExistingChunk: true,
                },
                zrender: {
                    chunks: 'all',
                    name: 'zrender',
                    test: /[\\/]node_modules[\\/](zrender)[\\/]/,
                    priority: 20,
                    reuseExistingChunk: true,
                },
                moment: {
                    chunks: 'all',
                    name: 'moment',
                    test: /[\\/]node_modules[\\/](moment)[\\/]/,
                    priority: 20,
                    reuseExistingChunk: true,
                },
                dayjs: {
                    chunks: 'all',
                    name: 'dayjs',
                    test: /[\\/]node_modules[\\/](dayjs)[\\/]/,
                    priority: 20,
                    reuseExistingChunk: true,
                },
                // vendors规则命中
                vendors: {
                    name: 'vendors',
                    test: /[\\/]node_modules[\\/]/,
                    priority: -10,
                    reuseExistingChunk: true,
                },
                // 默认的配置，vendors规则不命中的话，就会命中这里
                default: {
                    name: 'default',
                    minChunks: 2, // 引用超过两次的模块 -> default
                    priority: -20,
                    reuseExistingChunk: true,
                },
            },
        },
    },
});
